﻿using System.Collections.Generic;
using log4net;
using MySql.Data.MySqlClient;

namespace Possan.MySQL.Providers
{
	class ProfileCache
	{
		private string _conneString;
		private string _profiletablename;
		private static object _lockobject = new object();
		private static Dictionary<string, ProfileCacheData> _cachedata = new Dictionary<string, ProfileCacheData>();
		private ILog _log = LogManager.GetLogger(typeof(ProfileCache));
		
		public ProfileCache(string connectionstring)
		{
			_conneString = connectionstring;
			_profiletablename = "aspnet_profile";
		}

		public ProfileCacheData Get(string userid)
		{
			if (string.IsNullOrEmpty(userid))
				return null;

			ProfileCacheData ret = null;

			lock (_lockobject)
			{
				if (_cachedata.ContainsKey(userid))
					ret = _cachedata[userid];
			}

			if (ret != null)
				return ret;

			_log.Debug("Loading profile data for userid " + userid);

			using (var conn = new MySqlConnection(_conneString))
			{
				conn.Open();
				using (var cmd = conn.CreateCommand())
				{
					cmd.CommandText = @"select PropertyNames, PropertyValuesString from " + _profiletablename + @" where UserId = @a";
					cmd.Parameters.Add(new MySqlParameter("@a", userid));
					using (var rdr = cmd.ExecuteReader())
					{
						if (rdr.Read())
						{
							ret = new ProfileCacheData();
							ret.Names = rdr["PropertyNames"].ToString();
							ret.Data = rdr["PropertyValuesString"].ToString();
						}
						rdr.Close();
					}
					cmd.Dispose();
				}
				conn.Close();
			}

			// TODO: lagra i cachen

			if (ret != null)
				lock (_lockobject)
				{
					if (_cachedata.ContainsKey(userid))
						_cachedata[userid] = ret;
					else
						_cachedata.Add(userid, ret);
				}

			return ret;
		}

		public void Save(string userid, ProfileCacheData prop)
		{
			if (string.IsNullOrEmpty(userid))
				return;

			if (prop == null)
				return;

			_log.Debug("Saving profile data for userid "+userid);

			using (var conn = new MySqlConnection(_conneString))
			{
				conn.Open();
				int previous_rows = 0;

				using (var cmd = conn.CreateCommand())
				{
					cmd.CommandText = @"select count(*) as n from " + _profiletablename + @" where UserId = @a";
					cmd.Parameters.Add(new MySqlParameter("@a", userid));
					using (MySqlDataReader rdr = cmd.ExecuteReader())
					{
						if (rdr.Read())
						{
							int.TryParse(rdr["n"].ToString(), out previous_rows);
						}
						rdr.Close();
					}
					cmd.Dispose();
				}

				_log.Debug("previous_rows=" + previous_rows);
				if (previous_rows == 0)
				{
					using (MySqlCommand cmd = conn.CreateCommand())
					{
						cmd.CommandText = @"insert into " + _profiletablename +
											@" ( PropertyNames, PropertyValuesString, LastUpdatedDate, UserId ) values ( @a, @b, current_timestamp, @c )";
						cmd.Parameters.Add(new MySqlParameter("@a", prop.Names));
						cmd.Parameters.Add(new MySqlParameter("@b", prop.Data));
						cmd.Parameters.Add(new MySqlParameter("@c", userid));
						cmd.ExecuteNonQuery();
						cmd.Dispose();
					}
				}
				else
				{
					using (MySqlCommand cmd = conn.CreateCommand())
					{
						cmd.CommandText = @"update " + _profiletablename +
											@" set PropertyNames=@a, PropertyValuesString=@b where userid = @c";
						cmd.Parameters.Add(new MySqlParameter("@a", prop.Names));
						cmd.Parameters.Add(new MySqlParameter("@b", prop.Data));
						cmd.Parameters.Add(new MySqlParameter("@c", userid));
						cmd.ExecuteNonQuery();
						cmd.Dispose();
					}
				}

				conn.Close();
			}

			Flush(userid);
		}


		public bool Delete(string userid)
		{
			if (string.IsNullOrEmpty(userid))
				return false;
			 
			_log.Debug("Deleting profile data for userid " + userid);

			using (var conn = new MySqlConnection(_conneString))
			{
				conn.Open();
				using (var cmd = conn.CreateCommand())
				{
					cmd.CommandText = @"delete from " + _profiletablename + @" where UserId = @a";
					cmd.Parameters.Add(new MySqlParameter("@a", userid));
					cmd.ExecuteNonQuery();
				}
				conn.Close();
			}

			Flush(userid);

			return true;
		}

		public void Flush(string userid)
		{
			// TODO: töm cachen

			lock (_lockobject)
			{
				if (_cachedata.ContainsKey(userid))
					_cachedata.Remove(userid);
			}

		}
	}
}
